<template>
  <div ref="container" class="timeline">
    <div ref="cursor" class="cursor">
      <TimelineCursor />
    </div>
    <div ref="timeline" class="timeline-container" @click="onSeekerClick">
      <canvas ref="timelineCanvas" class="timeline-canvas" />
    </div>
  </div>
</template>
<script setup lang="ts">
import { throttle } from 'quasar';
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue';
import TimelineCursor from './TimelineCursor.vue';
import { fancyTimeFormat } from 'src/utils/common';
import { useVideoStore } from 'src/stores/video-store';
const props = defineProps({
  duration: {
    type: Number,
    required: true,
  },
  zoom: {
    type: Number,
    required: true,
  },
  position: {
    type: Number,
    required: true,
  },
  color: {
    type: String,
    default: '#707070',
  },
});
let scale = 0;
function px2time(px: number) {
  // time = x / (scale * zoom)
  return px / (scale * props.zoom);
}
function time2px(time: number) {
  // x = (scale * zoom) * time;
  return scale * props.zoom * time;
}
function onSeekerClick(e: MouseEvent) {
  scale = container.value!.clientWidth / props.duration;
  videoStore.seekTo(px2time(props.position + e.offsetX));
}
const emit = defineEmits(['update:position']);
const container = ref<HTMLDivElement>();
const timelineCanvas = ref<HTMLCanvasElement>();
let timelineCtx: CanvasRenderingContext2D | null = null;
const cursor = ref<HTMLDivElement>();
const videoStore = useVideoStore();
const currentTime = computed<number>(() => videoStore.currentTime);
const isPlaying = computed<boolean>(() => videoStore.isPlaying);
function update() {
  if (cursor.value) {
    if (props.duration !== 0) {
      scale = container.value!.clientWidth / props.duration;
      let x = time2px(currentTime.value) - props.position - 5;
      if (x > container.value!.clientWidth / 2 && isPlaying.value) {
        let position =
          time2px(currentTime.value) - container.value!.clientWidth / 2;
        emit('update:position', position);
        x = container.value!.clientWidth / 2 - 5;
      }
      cursor.value.style.left = `${x}px`;
    } else {
      cursor.value.style.left = '0px';
    }
  }
  timelineCanvas.value!.width = container.value!.clientWidth;
  updateTimeline();
  // scrollArea.value?.setScrollPosition('horizontal', props.position);
}
function drawLineByTime(time: number) {
  if (timelineCtx) {
    const x = time2px(time) - props.position;
    timelineCtx.strokeStyle = props.color;
    timelineCtx.lineWidth = 1.5;
    timelineCtx.beginPath();
    timelineCtx.moveTo(x, 0);
    timelineCtx.lineTo(x, 10);
    timelineCtx.stroke();
  }
}
function drawTimeTextByTime(time: number) {
  if (timelineCtx) {
    const x = time2px(time) - props.position;
    timelineCtx.fillStyle = props.color;
    timelineCtx.font = '11px';
    timelineCtx.fillText(`${fancyTimeFormat(Math.floor(time))}s`, x - 15, 20);
  }
}
function updateTimeline() {
  // let startTime = px2time(props.position);
  let endTime = px2time(props.position + container.value!.clientWidth);
  if (endTime === Infinity) {
    return;
  }
  let timeGapPx = time2px(1) - time2px(0);
  let timeGap = 1; // by second
  if (timeGapPx < 40 && timeGapPx > 30) {
    timeGap = 1;
  } else if (timeGapPx < 30 && timeGapPx > 20) {
    timeGap = 2;
  } else if (timeGapPx < 20 && timeGapPx > 10) {
    timeGap = 5;
  } else if (timeGapPx < 10 && timeGapPx > 5) {
    timeGap = 10;
  } else if (timeGapPx < 5 && timeGapPx > 1) {
    timeGap = 30;
  } else if (timeGapPx < 1 && timeGapPx > 0) {
    timeGap = 60;
  }
  let sec = timeGap;
  if (timelineCtx) {
    timelineCtx.clearRect(
      0,
      0,
      timelineCanvas.value!.width,
      timelineCanvas.value!.height
    );
    while (sec < endTime) {
      drawLineByTime(sec);
      drawTimeTextByTime(sec);
      sec += timeGap;
    }
  }
}
const fixedResize = throttle(update, 250);
onMounted(() => {
  timelineCtx = timelineCanvas.value!.getContext('2d');
  timelineCanvas.value!.height = 36;
  window.addEventListener('resize', fixedResize);
  update();
});
onBeforeUnmount(() => {
  window.removeEventListener('resize', fixedResize);
});
watch(currentTime, () => {
  update();
});
watch(
  () => props.position,
  () => {
    update();
  }
);
watch(
  () => props.zoom,
  () => {
    update();
  }
);
watch(
  () => props.duration,
  (newValue, oldValue) => {
    if (newValue !== oldValue) {
      update();
    }
  }
);
function addMarker() {}
defineExpose([addMarker]);
</script>
<style lang="scss" scoped>
.timeline {
  width: 100%;
  height: 384px;
  position: relative;
  overflow-x: hidden;
  .cursor {
    position: absolute;
    left: -5px;
    z-index: 10;
  }
  .seeker {
    width: 100%;
    height: 35px;
  }
  .timeline-container {
    width: 100%;
    height: 37px;
    position: absolute;
    top: 0px;
  }
}
</style>
